"""工单管理"""
from datetime import datetime
from typing import Optional, List

from fastapi import APIRouter, Depends, Path, Query, Body

from app.common.auth import check_permission
from app.common.common import DbDep, AuditLogDep
from app.crud import work_order_crud
from app.schemas.user_schemas import UserInDB
from app.schemas.work_order_schemas import (
	WorkOrderCreate, WorkOrderUpdate, WorkOrderResponse,
	WorkOrderDetailResponse, WorkOrderDispatchRequest, WorkOrderProcessRequest,
	WorkOrderResolveRequest, WorkOrderCloseRequest, WorkOrderQuery,
	WorkOrderTimelineResponse
)
from app.service import work_order_service
from common.base_enums import WorkOrderStatus
from common.exceptions import BizException, ErrorCode
from common.response import ApiResponse, PaginatedResponse

router = APIRouter(prefix="/work-orders", tags=["工单管理"])

# 权限依赖
require_work_order_manage = check_permission("work_order:manage")
require_work_order_view = check_permission("work_order:view")


@router.get("/", response_model=ApiResponse[PaginatedResponse[WorkOrderResponse]], summary="获取工单列表")
async def list_work_orders(
		db: DbDep,
		page: int = Query(1, ge=1, description="页码"),
		size: int = Query(20, ge=1, le=100, description="每页大小"),
		status: Optional[List[str]] = Query(
			None,
			alias="status[]",
			description="状态列表筛选，可多选"
		),
		assignee_code: Optional[str] = Query(None, description="负责人筛选"),
		device_id: Optional[int] = Query(None, description="设备ID筛选"),
		source_type: Optional[str] = Query(None, description="来源类型筛选"),
		station_id: Optional[int] = Query(None, description="台区ID筛选"),
		start_time: Optional[datetime] = Query(None, description="开始时间"),
		end_time: Optional[datetime] = Query(None, description="结束时间"),
		_: UserInDB = Depends(require_work_order_view)
) -> ApiResponse[PaginatedResponse[WorkOrderResponse]]:
	"""
	分页获取工单列表
	支持多个状态同时筛选，例如: ?status=CREATED&status=DISPATCHED
	"""
	# 转换状态参数
	status_list = None
	if status:
		status_list = []
		for s in status:
			try:
				status_list.append(WorkOrderStatus(s))
			except ValueError:
				raise BizException.from_error_code(ErrorCode.BAD_REQUEST, message=f"无效的状态值: {s}")

	# 转换来源类型参数
	source_type_enum = None
	if source_type:
		try:
			from common.base_enums import WorkOrderSourceType
			source_type_enum = WorkOrderSourceType(source_type)
		except ValueError:
			raise BizException.from_error_code(ErrorCode.BAD_REQUEST, message=f"无效的来源类型值: {source_type}")

	query = WorkOrderQuery(
		page=page,
		size=size,
		status=status_list,
		assignee_code=assignee_code,
		device_id=device_id,
		source_type=source_type_enum,
		station_id=station_id,
		start_time=start_time,
		end_time=end_time,
	)

	total, work_orders = await work_order_crud.get_work_order_list(db, query)

	work_order_responses = []
	for work_order in work_orders:
		# 使用model_validate而不是直接添加对象
		work_order_responses.append(WorkOrderResponse.model_validate(work_order))

	paginated_data = PaginatedResponse[WorkOrderResponse](
		total=total,
		items=work_order_responses,
		page=page,
		size=size,
		pages=(total + size - 1) // size,
		has_next=page * size < total,
		has_prev=page > 1
	)

	return ApiResponse.success(paginated_data)


@router.post("/", response_model=ApiResponse[dict], summary="创建工单")
async def create_work_order(
		db: DbDep,
		_audit: AuditLogDep,
		payload: WorkOrderCreate,
		current_user: UserInDB = Depends(require_work_order_manage)
) -> ApiResponse[dict]:
	"""
	创建新的工单
	"""
	try:
		work_order_id = await work_order_crud.create_work_order(db, payload, current_user.user_code)
		return ApiResponse.success({"id": work_order_id}, message="工单创建成功")
	except Exception as e:
		raise BizException.from_error_code(ErrorCode.INTERNAL_SERVER_ERROR, message=f"创建工单失败: {str(e)}")


@router.get("/{work_order_id}", response_model=ApiResponse[WorkOrderDetailResponse], summary="获取工单详情")
async def get_work_order_detail(
		db: DbDep,
		work_order_id: int = Path(..., description="工单ID"),
		_: UserInDB = Depends(require_work_order_view)
) -> ApiResponse[WorkOrderDetailResponse]:
	"""
	根据ID获取工单详情（包含日志）
	"""
	detail = await work_order_crud.get_work_order_detail(db, work_order_id)
	if not detail:
		raise BizException.from_error_code(ErrorCode.NOT_FOUND, message="工单不存在")

	work_order = detail["work_order"]
	logs = detail["logs"]

	response = WorkOrderDetailResponse(
		id=work_order.id,
		code=work_order.code,
		title=work_order.title,
		source_type=work_order.source_type,
		alarm_id=work_order.alarm_id,
		device_type=work_order.device_type,
		device_id=work_order.device_id,
		priority=work_order.priority,
		description=work_order.description,
		status=work_order.status,
		assignee_code=work_order.assignee_code,
		expect_finish_time=work_order.expect_finish_time,
		solution=work_order.solution,
		close_comment=work_order.close_comment,
		closed_by=work_order.closed_by,
		closed_at=work_order.closed_at,
		ext=work_order.ext,
		created_at=work_order.created_at,
		updated_at=work_order.updated_at,
		logs=logs
	)

	return ApiResponse.success(response)


@router.put("/{work_order_id}", response_model=ApiResponse[dict], summary="更新工单")
async def update_work_order(
		db: DbDep,
		_audit: AuditLogDep,
		work_order_id: int = Path(..., description="工单ID"),
		payload: WorkOrderUpdate = Body(...),
		current_user: UserInDB = Depends(require_work_order_manage)
) -> ApiResponse[dict]:
	"""
	更新工单信息
	"""
	success = await work_order_crud.update_work_order(db, work_order_id, payload, current_user.user_code)
	if not success:
		raise BizException.from_error_code(ErrorCode.NOT_FOUND, message="工单不存在")

	return ApiResponse.success(message="工单更新成功")


@router.delete("/{work_order_id}", response_model=ApiResponse[dict], summary="删除工单")
async def delete_work_order(
		db: DbDep,
		_audit: AuditLogDep,
		work_order_id: int = Path(..., description="工单ID"),
		current_user: UserInDB = Depends(require_work_order_manage)
) -> ApiResponse[dict]:
	"""
	删除工单（逻辑删除）
	"""
	success = await work_order_crud.delete_work_order(db, work_order_id, current_user.user_code)
	if not success:
		raise BizException.from_error_code(ErrorCode.NOT_FOUND, message="工单不存在")

	return ApiResponse.success(message="工单删除成功")


@router.put("/{work_order_id}/dispatch", response_model=ApiResponse[dict], summary="分派工单")
async def dispatch_work_order(
		db: DbDep,
		_audit: AuditLogDep,
		work_order_id: int = Path(..., description="工单ID"),
		payload: WorkOrderDispatchRequest = Body(...),
		current_user: UserInDB = Depends(require_work_order_manage)
) -> ApiResponse[dict]:
	"""
	分派工单给负责人
	"""
	try:
		await work_order_service.dispatch_work_order(
			db=db,
			work_order_id=work_order_id,
			assignee_code=payload.assignee_code,
			expect_finish_time=payload.expect_finish_time,
			comment=payload.comment,
			operator_code=current_user.user_code
		)
		return ApiResponse.success(message="工单分派成功")
	except BizException:
		raise
	except Exception as e:
		raise BizException.from_error_code(ErrorCode.INTERNAL_SERVER_ERROR, message=f"分派工单失败: {str(e)}")


@router.put("/{work_order_id}/process", response_model=ApiResponse[dict], summary="处理工单")
async def process_work_order(
		db: DbDep,
		_audit: AuditLogDep,
		work_order_id: int = Path(..., description="工单ID"),
		payload: WorkOrderProcessRequest = Body(...),
		current_user: UserInDB = Depends(require_work_order_manage)
) -> ApiResponse[dict]:
	"""
	开始处理工单（接单）
	"""
	try:
		await work_order_service.process_work_order(
			db=db,
			work_order_id=work_order_id,
			comment=payload.comment,
			operator_code=current_user.user_code
		)
		return ApiResponse.success(message="工单处理成功")
	except BizException:
		raise
	except Exception as e:
		raise BizException.from_error_code(ErrorCode.INTERNAL_SERVER_ERROR, message=f"处理工单失败: {str(e)}")


@router.put("/{work_order_id}/resolve", response_model=ApiResponse[dict], summary="解决工单")
async def resolve_work_order(
		db: DbDep,
		_audit: AuditLogDep,
		work_order_id: int = Path(..., description="工单ID"),
		payload: WorkOrderResolveRequest = Body(...),
		current_user: UserInDB = Depends(require_work_order_manage)
) -> ApiResponse[dict]:
	"""
	提交工单解决方案
	"""
	try:
		await work_order_service.resolve_work_order(
			db=db,
			work_order_id=work_order_id,
			solution=payload.solution,
			comment=payload.comment,
			operator_code=current_user.user_code
		)
		return ApiResponse.success(message="工单解决成功")
	except BizException:
		raise
	except Exception as e:
		raise BizException.from_error_code(ErrorCode.INTERNAL_SERVER_ERROR, message=f"解决工单失败: {str(e)}")


@router.put("/{work_order_id}/close", response_model=ApiResponse[dict], summary="关闭工单")
async def close_work_order(
		db: DbDep,
		_audit: AuditLogDep,
		work_order_id: int = Path(..., description="工单ID"),
		payload: WorkOrderCloseRequest = Body(...),
		current_user: UserInDB = Depends(require_work_order_manage)
) -> ApiResponse[dict]:
	"""
	关闭工单
	"""
	try:
		await work_order_service.close_work_order(
			db=db,
			work_order_id=work_order_id,
			close_comment=payload.close_comment,
			operator_code=current_user.user_code
		)
		return ApiResponse.success(message="工单关闭成功")
	except BizException:
		raise
	except Exception as e:
		raise BizException.from_error_code(ErrorCode.INTERNAL_SERVER_ERROR, message=f"关闭工单失败: {str(e)}")


@router.get("/{work_order_id}/timeline", response_model=ApiResponse[WorkOrderTimelineResponse],
			summary="获取工单时间线")
async def get_work_order_timeline(
		db: DbDep,
		work_order_id: int = Path(..., description="工单ID"),
		_: UserInDB = Depends(require_work_order_view)
) -> ApiResponse[WorkOrderTimelineResponse]:
	"""
	获取工单流转时间线
	"""
	# 检查工单是否存在
	work_order = await work_order_crud.get_work_order_by_id(db, work_order_id)
	if not work_order:
		raise BizException.from_error_code(ErrorCode.NOT_FOUND, message="工单不存在")

	logs = await work_order_crud.get_work_order_logs(db, work_order_id)

	log_responses = []
	for log in logs:
		log_responses.append(log)

	return ApiResponse.success(WorkOrderTimelineResponse(items=log_responses))
